package com.bes.sdk.control;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.bes.sdk.device.HmDevice;
import com.bes.sdk.message.AncStatusMessage;
import com.bes.sdk.message.BaseMessage;
import com.bes.sdk.message.BatteryInfo;
import com.bes.sdk.message.DeviceInfoMessage;
import com.bes.sdk.message.AncSettings;
import com.bes.sdk.message.GestureInfo;
import com.bes.sdk.message.GestureMessage;
import com.bes.sdk.message.InEarInfo;
import com.bes.sdk.message.MyBudsInfo;
import com.bes.sdk.message.MyBudsMessage;
import com.bes.sdk.message.OTAInfo;
import com.bes.sdk.message.OTAInfoMessage;
import com.bes.sdk.message.SealingInfo;
import com.bes.sdk.message.SmartSwitchInfo;
import com.bes.sdk.utils.MessageID;
import com.bes.sdk.utils.StatusCode;

import java.util.List;

/**
 * General device control API.
 */
public interface DeviceStatusControl extends BaseControl
{
    /**
     * Get all the device info as HmDevice.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link DeviceInfoMessage}, which
     * {@link DeviceInfoMessage#getMsgID()} is {@link MessageID#DEVICE_LIST_INFO},
     * {@link DeviceInfoMessage#getMsgContent()}should be a list of {@link HmDevice}
     */
    void getDeviceInfo(@Nullable DeviceListener listener);

    /**
     * Set device name.
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#DEVICE_NAME},
     * {@link BaseMessage#getMsgContent()} new device name, type is {@link String}.
     */
    void setDeviceName(@NonNull HmDevice device, String deviceName, @Nullable DeviceListener listener);

    /**
     * Get enable ANC.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link AncStatusMessage}, which
     * {@link AncStatusMessage#getMsgID()} is {@link MessageID#ANC_STATUS},
     * {@link AncStatusMessage#getMsgContent()} includes all enabled ANC setting.
     */
    void getAncSetting(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Set enable ANC status
     * @param anc new ANC value
     * @param saveOrNot true save current AncSetting, otherwise only set current AncSetting.
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link AncStatusMessage}, which
     * {@link AncStatusMessage#getMsgID()} is {@link MessageID#ANC_STATUS},
     * {@link AncStatusMessage#getMsgContent()} only includes new changed Anc setting.
     */
    void setAncSetting(@NonNull HmDevice device, AncSettings anc, boolean saveOrNot, @Nullable DeviceListener listener);

    /**
     * Get AutoPause status, false for OFF, true for ON.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#AUTO_PAUSE},
     * {@link BaseMessage#getMsgContent()} is the current AutoPause status, type is {@link Boolean}, value can be:
     * <li>true -- ON
     * <li>false -- OFF
     */
    void getAutoPlayPauseStatus(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Set Auto Play Pause. Means if detected device is taken off, it should auto pause or not.
     * @param enableOrNot new AutoPause status.
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#AUTO_PAUSE},
     * {@link BaseMessage#getMsgContent()} is the new AutoPause status, type is {@link Boolean}, value can be:
     * <li>true -- ON
     * <li>false -- OFF
     */
    void setAutoPlayPauseStatus(@NonNull HmDevice device, boolean enableOrNot, @Nullable DeviceListener listener);

    /**
     * Get auto power off status: 0 means disable, non 0 means ON and the value is Auto Power Off interval,
     * means the device should auto power off for some condition, for example, no music playing for some time,
     * and so on.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#AUTO_POWER_OFF},
     * {@link BaseMessage#getMsgContent()} is current auto power off status, type is {@link Integer}, value can be:
     * <li>0 for OFF;
     * <li>other Non-zero means On and and the value is AutoOff interval. Means the device should auto power
     * off for some condition, for example, no music playing for some time, and so on.
     */
    void getAutoPowerOffStatus(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Set auto power off status.
     * @param autoPowerOff 0 means Off, non 0 means ON and the value is Auto Power Off interval, unit minute.
     *  max value 360 minutes.
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#AUTO_POWER_OFF},
     * {@link BaseMessage#getMsgContent()} is new auto power off status, which return type is {@link Integer}, value can be:
     * <li>0 for OFF;
     * <li>other Non-zero means On and and the value is AutoOff interval. Means the device should auto power
     * off for some condition, for example, no music playing for some time, and so on.
     */
    void setAutoPowerOffStatus(@NonNull HmDevice device, int autoPowerOff, @Nullable DeviceListener listener);

    /**
     * Get Multi-AI status, which one is currently activated.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#MULTI_AI_STATUS},
     * {@link BaseMessage#getMsgContent()} is current AI value, type is {@link Integer}, value can be:
     * <li>0 for OFF;
     * <li>1 for Google AI;
     * <li>2 for Amazon Alexa;
     * <li>3 for SIRI;
     * <li>4 for Tencent XiaoWei.
     */
    void getMultiAIStatus(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Set Multi-AI status
     * @param ai
     * <li>0 for OFF;
     * <li>1 for Google AI;
     * <li>2 for Amazon Alexa;
     * <li>3 for SIRI;
     * <li>4 for Tencent XiaoWei.
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#MULTI_AI_STATUS},
     * {@link BaseMessage#getMsgContent()} is new AI value, type is {@link Integer}, value can be:
     * <li>0 for OFF;
     * <li>1 for Google AI;
     * <li>2 for Amazon Alexa;
     * <li>3 for SIRI;
     * <li>4 for Tencent XiaoWei.
     */
    void setMultiAIStatus(@NonNull HmDevice device, int ai, @Nullable DeviceListener listener);

    /**
     * Check device A2DP connection status. It's useful especially for iOS to detect the A2DP connection status.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link A2DPConnectionMessage}, which
     * {@link A2DPConnectionMessage#getMsgID()} is {@link MessageID#A2DP_STATUS},
     * {@link A2DPConnectionMessage#getMsgContent()} is current A2DP status, type is {@link A2DPConnection}
     */
    void getA2DPConnectionStatus(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Get FindMyBuds setting.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link MyBudsMessage}, which
     * {@link MyBudsMessage#getMsgID()} is {@link MessageID#FIND_ME_STATUS},
     * {@link MyBudsMessage#getMsgContent()} is current MyBuds status, which type is {@link MyBudsInfo}
     */
    void getFindMyBuds(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Set FindMyBuds settings.
     *
     * @param myBudsInfo
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link MyBudsMessage}, which
     * {@link MyBudsMessage#getMsgID()} is {@link MessageID#FIND_ME_STATUS},
     * {@link MyBudsMessage#getMsgContent()} is new MyBuds status, type is {@link MyBudsInfo}
     */
    void setFindMyBuds(@NonNull HmDevice device, MyBudsInfo myBudsInfo, @Nullable DeviceListener listener);

    /**
     * Get gesture action with specified gestureId.
     * @param gestureId see gesture ID in {@link GestureInfo#getGestureId()},
     * if gestureId is {@link GestureInfo#ALL}, return all gestures both on left and right in callback.
     * if gestureId is {@link GestureInfo#LEFT_ALL}, return gestures on left in callback.
     * if gestureId is {@link GestureInfo#RIGHT_ALL}, return gestures on right in callback.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link GestureMessage}, which
     * {@link GestureMessage#getMsgID()} is {@link MessageID#GESTURE_STATUS},
     * {@link GestureMessage#getMsgContent()} is current Gesture status, type is {@link List <GestureInfo>}
     */
    void getGestureStatus(@NonNull HmDevice device, int gestureId, @Nullable DeviceListener listener);

    /**
     * Reset gesture configuration.
     * @param gesture {@link GestureInfo#LEFT_ALL} reset all gesture on left,
     * {@link GestureInfo#RIGHT_ALL} reset all gesture on right.
     * {@link GestureInfo#ALL} reset all gesture both on left and right.
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link GestureMessage}, which
     * {@link GestureMessage#getMsgID()} is {@link MessageID#GESTURE_STATUS},
     * {@link GestureMessage#getMsgContent()} is new Gesture status, type is {@link List<GestureInfo>}
     */
    void resetGestureStatus(@NonNull HmDevice device, int gesture, @Nullable DeviceListener listener);

    /**
     * Set gesture configuration, only update gesture-action pair specified in parameter gestureInfoList.
     * @param gestureInfoList
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link GestureMessage}, which
     * {@link GestureMessage#getMsgID()} is {@link MessageID#GESTURE_STATUS},
     * {@link GestureMessage#getMsgContent()} is new Gesture status, type is {@link List<GestureInfo>}
     */
    void setGestureStatus(@NonNull HmDevice device, List<GestureInfo> gestureInfoList, @Nullable DeviceListener listener);

    /**
     * Check whether AI OTA in progress or not. Since AI OTA is highest priority, we need to check
     * the status before start firmware OTA.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link OTAInfoMessage}, which
     * {@link OTAInfoMessage#getMsgID()} is {@link MessageID#OTA_STATUS},
     * {@link OTAInfoMessage#getMsgContent()} is new OTA status, type is {@link OTAInfo}
     */
    void getRunningOTAInfo(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Check TWS connection status
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#TWS_STATUS},
     * {@link BaseMessage#getMsgContent()} is current TWS connection status, type is {@link Boolean}, value can be:
     * <li>true - slave connected;
     * <li>false - slave disconnected;
     */
    void getTwsConnectStatus(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * App requests to sync CRC with device.
     *
     * CRC generally is used for simple authentication or multipoint connect scenario.
     *
     * CRC is usually bytes array with size of 2, which is generate based on the Bluetooth
     * name of mobile. Communication between device and app will use CRC to make sure the
     * message is from the right device that currently connected.
     *
     * It's also useful for multipoint connection scenario. Imagine the device connected with
     * multiple mobile phones, that means two possible CRC can be generated from two mobile
     * Bluetooth names. This API will request the device to use specified CRC for communication
     * with app installed on specified mobile.
     *
     * @param crc CRC value of device name {@link #setDeviceName(HmDevice, String, DeviceListener)}
     * @param listener
     * {@link DeviceListener#onChanged (HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#SYNC_CRC_STATUS},
     * {@link BaseMessage#getMsgContent()} is new crc value, type is {@link String}
     */
    void syncCrcWithDevice(@NonNull HmDevice device, String crc, @Nullable DeviceListener listener);

    /**
     * Get current sealing status.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#SEALING_STATUS},
     * {@link BaseMessage#getMsgContent()} is current sealing status, type is {@link SealingInfo}
     */
    void getSealingStatus(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Get current in ear status.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#IN_EAR_STATUS},
     * {@link BaseMessage#getMsgContent()} is current in ear status, type is {@link InEarInfo}
     */
    void getInEarStatus(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Get current smart switch settings.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#SMART_SWITCH_STATUS},
     * {@link BaseMessage#getMsgContent()} is current smart switch information, type is {@link SmartSwitchInfo}
     */
    void getSmartSwitchStatus(@NonNull HmDevice device, @Nullable DeviceListener listener);

    /**
     * Set smart switch status
     * @param info
     * @param listener
     * {@link DeviceListener#onChanged(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#SMART_SWITCH_STATUS},
     * {@link BaseMessage#getMsgContent()} is new smart switch information, type is {@link SmartSwitchInfo}
     */
    void setSmartSwitchStatus(@NonNull HmDevice device, SmartSwitchInfo info, @Nullable DeviceListener listener);
	
    /**
     * Get current battery status.
     * @param listener
     * {@link DeviceListener#onRead(HmDevice device, StatusCode code, BaseMessage message)} callback will indicate the operation result.
     * <p>parameter code in deviceCallback, {@link StatusCode#STATUS_SUCCESS} of means success, others for fail with reasons.
     * <p>parameter message in deviceCallback is an object of {@link BaseMessage}, which
     * {@link BaseMessage#getMsgID()} is {@link MessageID#BATTERY_STATUS},
     * {@link BaseMessage#getMsgContent()} is current battery status, type is {@link BatteryInfo}
     */
    void getBatteryInfo(@NonNull HmDevice device, @Nullable DeviceListener listener);
}
